from django.utils.deprecation import MiddlewareMixin
from django.http.response import HttpResponseServerError, HttpResponse
from django.conf import settings
from libs.wx.utils import PayUtil
from importlib import import_module

# 该中间件用于处理微信支付的支付结果通知
# 原理说明：该中间件会捕获url为/wx/pay/notify/的请求，并验证请求结果和签名，通过后交给配置中指定的方法处理。
# 注意事项：请务必把该中间件置于认证中间件(libs.middleware.AuthenticationMiddleware)之前之前之前，防止请求被认证中间件拦截。
# 使用说明：
#   1. 在public.settings.py的SERVICES.WX_PAY中配置NOTIFY_HANDLER，指定处理通知的函数，例如：'order.views.wx_pay_notify'，该中
#      间件会去order包下的views模块中加载wx_pay_notify方法来执行
#   2. 该函数需要接收3个参数(订单号，支付金额，支付时间)，返回bool值，表示是否处理成功(如果不成功微信会重复发起支付通知)
#   3. 该函数需要支持可能出现的重复请求
#   3. 注意校验支付金额是否与数据库中的订单金额一致，防止数据泄漏导致出现“假通知”，造成资金损失
#
# 处理支付通知函数例子：
# def wx_pay_notify(out_trade_no, total_fee, time_end, transaction_id):
#     order = Order.objects.get(order_sn=out_trade_no)
#     if float(order.order_total_price) == int(total_fee) / 100:
#         order.order_status = 1
#         order.pay_channel = 1
#         order.escrow_trade_no = transaction_id
#         order.pay_time = human_time(datetime.strptime(time_end, '%Y%m%d%H%M%S'))
#         order.save()
#     return True

MCH_KEY = settings.SERVICES['WX_PAY']['MCH_KEY']
module, method = settings.SERVICES['WX_PAY']['NOTIFY_HANDLER'].rsplit('.', 1)
handler = getattr(import_module(module), method)


class WxPayNotifyMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if request.path == '/wechat/pay/notify/':
            data, _, _ = PayUtil.parse_pay_response(request.body, MCH_KEY)
            if handler(data.out_trade_no, data.total_fee, data.time_end, data.transaction_id, data.get('attach')):
                return HttpResponse(PayUtil.dict_to_xml({'return_code': 'SUCCESS', 'return_msg': 'OK'}))
            return HttpResponseServerError()
